Parallax-Scrolling

← Zurück zum Forum

Ich beschäftige mich gerade mit Parallax-Scrolling und da es im neuen und alten Forum keine ausreichende Diskussion darüber gibt, möchte ich es hier gerne öffentlich diskutieren. Am Ende soll ein relativ einfacher aber nachvollziehbarer Assembler-Code rauskommen, den jeder in sein mögliches Programm einbauen bzw. anpassen /erweitern kann.

AntwortZitat

... mein Beispielcode ist nun fertig und ich werde das hier jetzt Schritt für Schritt posten und erklären! Folgende Kriterien sollte der Code haben:

  1. Da ich mein nächstes Spiel wohl im Antic-Modus D erstellen werde (Bitmap 160x96, 4 Farben) sollte die Displaylist auch entsprechend für dieses Beispiel aufgebaut werden.
  2. Da ich mehr als 4 Farben reinbringen möchte, sollte die Displaylist entsprechend mit 3 Displaylist-Interrupts manipuliert werden.
  3. Der Code sollte einfach und kurz sein. Ich wollte den Code so machen, daß alles gut lesbar drin ist (keine Includes...).
  4. Der Code sollte nur ein einfaches Feinscrolling in drei unterschiedlichen Geschwindigkeiten darstellen, auf ein Grobscroll habe ich hier extra verzichtet - ein Grobscroll kann ich gerne später noch in den Code integrieren wenn erwünscht.

Vorab der komplette Code hier, den ich später pö a pö erkläre - gleich ruft aber erstmal die Sonne und der Garten 😉

        org $1000       

screen = 240
scrolm1 = 242
scrolm2 = 243
scrolm3 = 244
scrolindex =245
delay = 246     

VDSLST = 512
NMIEN = 54286
wsync = 54282
hscrol = 54276
rtclok = 18
colpf1 = 53271



            .proc main

            mwa #dlist1 560

            lda #<dli0
            sta VDSLST
            lda #>dli0
            sta VDSLST+1
            lda #192
            sta NMIEN
            ldy #0
            lda #0 
            sta 710
            lda #15
            sta scrolm1
            sta scrolm2
            sta scrolm3

main2       
            ldx #0
            mva #$a0 screen+1
            mva #$4f screen
@           lda #170
            sta (screen),y
            clc
            lda screen
            adc #48
            sta screen
            lda screen+1
            adc #0
            sta screen+1
            clc
            inx
            cpx #90
            bne @-

loop        ldx #15
            clc
@       
            inc scrolindex
            dec scrolm3
            mva #2 delay
            jsr wartes
            dec scrolm3
            dec scrolm2
            mva #2 delay
            jsr wartes
            dec scrolm1
            dec scrolm2
            dec scrolm3
            mva #2 delay
            jsr wartes

            #if .byte scrolm1<=#1
            mva #15 scrolm1
            #end
            #if .byte scrolm2<=#1
            mva #15 scrolm2
            #end
            #if .byte scrolm3<=#1
            mva #15 scrolm3
            #end

            dex
            stx 250
            clc
            ldx 250
            cpx #1
            bne @-
            jmp loop

            .endp



            ; ---------------------------- S U B R O U T I N E N ----------------------------------

            .proc wartes
            clc
            ldx delay ; Warteschleife
st          
            lda RTCLOK+2

wa   
            cmp RTCLOK+2 
            beq wa 
            dex            
            bpl st 
            rts
     .endp   
            .proc dlist1
            .by 112,112,112,93  ;64+13+16
            .by 40,160,29   
            .by 29
            .by 157
:19         .by 29
            .by 157
:33         .by 29
            .by 29
:27         .by 29
            .by 157
            .by 65
            .wo dlist1
            .endp
            .proc dli0
            phr
            sta wsync
            mva #55 colpf1
            mva scrolm2 hscrol
            sta wsync
            mwa #dli1 512
            plr
            rti
            .endp
            .proc dli1
            phr
            sty wsync
            mva scrolm3 hscrol
            mva #111 colpf1 
            sta wsync
            mwa #dli2 512
            plr
            rti
            .endp
            .proc dli2
            phr
            sta wsync
            mva scrolm1 hscrol
            mva #222 colpf1
            sta wsync
            mwa #dli0 512
            plr
            rti
            .endp
AntwortZitat

... ich bin noch dabei in meine Routine das Grobscroll einzubauen, dabei gab es nun doch mehr Probleme als ich gedacht hatte. Das Timing ist nicht so einfach und einen 4k Bildschirm im DLI zu bewegen geht nicht. Das kostet zu viel Zeit. Im VBI ist das eher möglich in Portionen, flackert aber.

Ich versuche das Grobscroll nun durch Displaylist-Manipulation zu realisieren, es gibt da ein paar Vorlagen, die ich aber verdammt kompliziert finde. Das versuche ich jetzt selber zu basteln und habe da einen ganz guten Ansatz, der für eine Zeile schon zu funktionieren scheint. Nun will ich das noch so anpassen, daß das auch für den gesamten Bildschirm funktioniert...

AntwortZitat

Du musst doch eigentlich nur die Startadresse im DL ändern und nicht den Bildschirm scrollen.

Also quasi so: Der Bildschirm ist eine Lupe, die Du über die Zeitung schiebst... Dabei bleibt die Zeitung liegen.

In jeder Zeile machst Du einen LMS und musst dann nur diese Adresse anpassen. Die Daten müssen dann natürlich auch gut im Speicher liegen. Nehmen wir an, Du hast einen Level, der 3 normale Bildschirme breit ist, dann hast Du also 3*40 Bytes je Zeile und so lautet die DL in etwa so:

     .he 4d
chg  .wo screen
     .he 4d
chg1 .wo screen+120
     .he 4d
chg2 .wo screen+240

Wenn einmal fine scroll durch ist, müssen nun die ganzen chg Werte um ein Byte angepasst werden, bzw. bei hoch oder runter um 120 Bytes.

Hoffe, das ist so zu verstehen.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

Hallo und vielen Dank, den Code von dir schaue ich gleich mal an... Ich denke mein Ansatz war wohl ganz ähnlich:

        org $1000

        icl '../hardware.txt'

delay = 240 
var1 = 241

        .proc main

        mwa #dlist1 560


loop    lda random
        sta 39976+79
        ldx #80
@       txa
        sta dlist1+10
        sta var1
        lda random
        sta 39976,x
        sta 39976,x-40
        mva #4 delay
        jsr wartes
        ldx var1
        clc
        inx
        cpx #120
        bne @-
        lda #80
        sta dlist1+10
        jmp loop

        .endp

    ;---------- Subroutinen ---------

        .proc dlist1
dlist   .by 117,117,117
        .by 66,0,156        ; 39976
        .by 66,40,156
        .by 66,80,156
        .by 66,160,156
:20     .by 2
        .by 65
        .wo dlist

        rts

        .endp

        .proc wartes
            clc
            ldx delay ; Warteschleife
st          
            lda RTCLOK+2
wa   
            cmp RTCLOK+2 
            beq wa 
            dex            
            bpl st 
            rts
     .endp   


        run main

Das scrollt erstmal nur eine Zeile. Die Zeilenblöcke müssen ja bei Parallax unterschiedlich den Grobscroll ausführen können. Zusätzlich geht es aber meines Erachtens nicht einfach nur wie von dir beschrieben wie mit einer Lupe über die Speicherstellen zu schauen, denn der Scroll geht ja zB von rechts nach links und alles was links aus dem Bildschirm rausscrollt verschwindet und rechts zB kommt etwas neues (Landschaft) rein. Geht man einfach nur über den Speicherbereich, dann ist man zu schnell am Speicherende!

AntwortZitat

Ja, das mit "Lupe über Zeitung"-Scrolling hat den Nachteil, dass die Zeitung komplett fertig daliegen muss und somit Platz benötigt. Man kann mit etwas mehr Aufwand immer nur rechts ein Zeichen mehr haben und in einem zweiten Screen alles um 1 Byte nach links verschoben haben. Dann muss der gesamte Bildschirm umgeschaltet werden, wenn dann alles dorthin kopiert worden ist. Bei Bitmap Grafik aber imho eher zu viel Kopierarbeit.

Irgendwo hatte aber mal jemand die Methode vom Gameboy erklärt. Dort scrollt man auch irgendwie mit der Lupe, aber nur über 2 Bildschirmbreiten. Was links raus geht, bekommt irgendwas von rechts reinkopiert, bis dann ganz rechts angekommen, das selbe im linken Bereich drin ist, dann wird direkt dorthin zurückgesprungen und wieder nach dem Muster neu begonnen. So ganz habe ich das noch nicht geschnallt und weiß gerade nicht mehr, wo ich das gelesen hatte... Eigentlich wollte ich mir den Link speichern - naja, habe ich dann wohl nicht getan 🙄

Hmmm vielleicht ja so...

1,2,3..40,41 Ausgangslage 41,2,3..41,42 erstes Zeichen links raus (also da, wo vorher die 1 war, kommt auch das 41. Zeichen hin, aber der Bildschirm beginnt nun bei 2) 41,42,3..42,43 zweites Zeichen links raus (da wo, die 2 war kommt auch das 42. Zeichen hin, BS beginnt bei 3)

Und wenn dann 40 raus ist, steht ja 41 bis 80 auch dort, wo vorher 1 bis 40 stand, also wird dann mit dem LMS wieder an den Anfang verzweigt und das 81. Byte kommt als nächstes dann an die Stelle, wo anfangs das 41. Byte stand.

Auf diese Weise muss man die LMS in der DL aktualisieren und 2 mal in den Speicher jeweils das eine Byte je Zeile kopieren. Bei 200 Zeilen also 400 Bytes kopieren plus 200 LMS Words aktualisieren. Das könnte schon noch klappen.

Aber irgendwoher muss der Level ja auch kommen. Wenn er dort in "komprimierter" Form ist, wird es sicherlich auch ordentlich Hirnschmalz kosten, das zu dekodieren.

PP´s of STARSOFTBerlin____github|meine Webseite|Demozoo

AntwortZitat

... ganz genau ... schau dir bitte mal meinen letzten Code an. Da habe ich es bereits für eine Zeile recht einfach realisiert. Rechts kommt per Random immer ein neues Zeichen rein und das gescrollte Zeichen wird zwischengespeichert. Daher braucht man einen doppelten Speicherbereich. Nach 40 Grobscroll schaltet man wieder zurück wo aber die aktuelle Zeile (als Doppel) liegt und dann gehts wieder erneut los.... Noch habe ich aber Probleme mit mehreren Zeilen... das bekommt man aber hin!

AntwortZitat

... den Code auf mehrere Zeilen zu erweitern (am Ende soll ja der ganze Bildschirm via Displaylist-Manipulation scrollen) war nicht so ganz einfach, jetzt habe ich es aber geschafft die ersten drei Zeilen zu scrollen - und damit ist auch die Logik für die anderen Zeilen klar!

Anbei der Code:

        org $1000


        icl '../hardware.txt'

delay = 240 
var1 = 241



        .proc main

        mwa #dlist1 560


loop    


        ldx #00

@       txa
        sta dlist1+7
        sta var1
        lda random
        sta 39936,x+39
        sta 39936,x-1
        txa
        adc #80
        sta dlist1+10
        lda random
        sta 40016,x+39
        sta 40016,x-1
        txa
        sta dlist1+13
        lda random
        sta 40192,x+39
        sta 40192,x-1


        mva #6 delay
        jsr wartes
        ldx var1
        clc
        inx
        cpx #40
        bne @-

        lda #0
        sta dlist1+7
        sta dlist1+10
        sta dlist1+13

        jmp loop



        .endp

    ;---------- Subroutinen ---------

        .proc dlist1

dlist   .by 117,117,117
        .by 66,0,156        ; 39976
        .by 66,80,156
        .by 66,160,156

        .by 66,0,157
        .by 66,80,157
        .by 66,160,157

        .by 66,0,158
        .by 66,80,158
        .by 66,160,158  

        .by 66,0,159
        .by 66,80,159
        .by 66,160,159  

        .by 66,0,160        ; 39976
        .by 66,80,160
        .by 66,160,160

        .by 66,0,161
        .by 66,80,161
        .by 66,160,161

        .by 66,0,162
        .by 66,80,162
        .by 66,160,162

        .by 66,0,163
        .by 66,80,163
        .by 66,160,163

        .by 65
        .wo dlist

        rts

        .endp

        .proc wartes
            clc
            ldx delay ; Warteschleife
st          
            lda RTCLOK+2

wa   
            cmp RTCLOK+2 
            beq wa 
            dex            
            bpl st 
            rts
     .endp   




        run main

Damit scrollt man jetzt via Displaylist, das Zeichen links fliegt immer raus und rechts schiebe ich ein neues Zeichen wieder rein (hier im Beispiel per Random). Damit kann man den Horizontalshooter laufen lassen - man muss das natürlich entsprechend noch mit dem Feinscroll verbinden.

Gruß Peter

AntwortZitat

... ich habe die ganze Zeit mir meine grauen Zellen zermartert, warum es nicht logisch mit den Zeilen so klappt, wie ich es erwartet habe... und ein wenig rumprobiert. Fakt scheint zu sein: Wenn man jede Zeile mit einer eigenen Adresse definiert, dann muss man die erste Zeile anders behandeln. Der erste 64+2 Befehl definiert ja normalerweise die erste Zeile (Antic 2 zB) mit dem Wert des Startes der Bildschirmadresse. Vorher kommen die 3 x 117 für den Overscan. Jetzt aber definiert der ersten Wert den Start des Overscans... also habe ich dafür einfach einen zusätzlichen Befehl eingeführt, den er jetzt für den Start des Overscans nimmt. Puh... ganz schön kompliziert und unerwartet. Habe ich da irgendwie einen Denkfehler, oder muss das so sein? Die Profis hier können das sicherlich ganz einfach erklären.... so geht es jetzt aber und anbei der korrekte Code mit dem Grobscroll der ersten drei Zeilen bei Antic 2. Ich werde jetzt noch in den nächsten Tagen den Code etwas schlanker und für den ganzen Bildschirmbereich machen - danach übertrage ich das dann auf mein Parallax-Beispiel, denn hier wird es zwingend benötigt!

Der Code:

                org $1000


        icl '../hardware.txt'

delay = 240 
var1 = 241



        .proc main

        mwa #dlist1 560


loop    

        ldx #0
@       txa
        sta dlist1+7
        sta var1
        lda random
        sta 39936,x+39
        sta 39936,x-1
        txa
        adc #80
        sta dlist1+10
        lda random
        sta 40016,x+39
        sta 40016,x-1
        txa
        adc #160
        sta dlist1+13
        lda random
        sta 40096,x+39
        sta 40096,x-1


        mva #6 delay
        jsr wartes
        ldx var1
        clc
        inx
        cpx #40
        bne @-

        lda #0
        sta dlist1+7
        sta dlist1+10
        sta dlist1+13

        jmp loop



        .endp

    ;---------- Subroutinen ---------

        .proc dlist1

dlist   .by 117,117,117
        .by 66,210,155
        .by 66,0,156        
        .by 66,80,156
        .by 66,160,156

        .by 66,0,157
        .by 66,80,157
        .by 66,160,157

        .by 66,0,158
        .by 66,80,158
        .by 66,160,158  

        .by 66,0,159
        .by 66,80,159
        .by 66,160,159  

        .by 66,0,160        
        .by 66,80,160
        .by 66,160,160

        .by 66,0,161
        .by 66,80,161
        .by 66,160,161

        .by 66,0,162
        .by 66,80,162
        .by 66,160,162

        .by 66,0,163
        .by 66,80,163
        .by 66,160,163

        .by 65
        .wo dlist

        rts

        .endp

        .proc wartes
            clc
            ldx delay ; Warteschleife
st          
            lda RTCLOK+2

wa   
            cmp RTCLOK+2 
            beq wa 
            dex            
            bpl st 
            rts
     .endp   




        run main

Interessiert das hier überhaupt, oder ist das etwas zu spezielles... immerhin wird man damit relativ einfach und vor allem ohne großen Rechenaufwand ein Grobscroll horizontal ausführen können, wo man eben nicht nur wie mit einer Lupe über den Speicher schaut...

AntwortZitat

hier der Code für den gesamten Bildschirm! Mit delay kann man die Geschwindigkeit verändern. Ich habe den Code extra zum Verständnis so hier mal gepostet, damit jeder gut nachvollziehen kann, wie er aufgebaut ist. In der Praxis wird man allerdings mit einer Matrix arbeiten und so den ganzen Code verschlanken und weniger redundant machen. Der Speicherbedarf beträgt ca. 2KB also etwas mehr als doppelt so viel wie ein Bildschirm Antic 2. Jede Zeile kann extra und eigenständig grobgescrollt werden. Für Antic 2 braucht man also 24 Zeilen (entsprechend Befehlsblöcke) und für Antic D dann 100 Zeilen.

        org $1000


        icl '../hardware.txt'

delay = 240 
var1 = 241


        .proc main

        mwa #dlist1 560

loop    

        ldx #0
@       txa
        sta dlist1+7
        sta var1
        lda random
        sta 256*156,x+39
        sta 256*156,x-1
        txa
        adc #80
        sta dlist1+10
        lda random
        sta 256*156+80,x+39
        sta 256*156+80,x-1
        txa
        adc #160
        sta dlist1+13
        lda random
        sta 256*156+160,x+39
        sta 256*156+160,x-1
        txa
        sta dlist1+16
        lda random
        sta 256*157,x+39
        sta 256*157,x-1
        txa
        adc #80
        sta dlist1+19
        lda random
        sta 256*157+80,x+39
        sta 256*157+80,x-1
        txa
        adc #160
        sta dlist1+22
        lda random
        sta 256*157+160,x+39
        sta 256*157+160,x-1
        txa
        sta dlist1+25
        lda random
        sta 256*158,x+39
        sta 256*158,x-1
        txa
        adc #80
        sta dlist1+28
        lda random
        sta 256*158+80,x+39
        sta 256*158+80,x-1
        txa
        adc #160
        sta dlist1+31
        lda random
        sta 256*158+160,x+39
        sta 256*158+160,x-1
        txa
        sta dlist1+34
        lda random
        sta 256*159,x+39
        sta 256*159,x-1
        txa
        adc #80
        sta dlist1+37
        lda random
        sta 256*159+80,x+39
        sta 256*159+80,x-1
        txa
        adc #160
        sta dlist1+40
        lda random
        sta 256*159+160,x+39
        sta 256*159+160,x-1
        txa
        sta dlist1+43
        sta var1
        lda random
        sta 256*160,x+39
        sta 256*160,x-1
        txa
        adc #80
        sta dlist1+46
        lda random
        sta 256*160+80,x+39
        sta 256*160+80,x-1
        txa
        adc #160
        sta dlist1+49
        lda random
        sta 256*160+160,x+39
        sta 256*160+160,x-1
        txa
        sta dlist1+52
        lda random
        sta 256*161,x+39
        sta 256*161,x-1
        txa
        adc #80
        sta dlist1+55
        lda random
        sta 256*161+80,x+39
        sta 256*161+80,x-1
        txa
        adc #160
        sta dlist1+58
        lda random
        sta 256*161+160,x+39
        sta 256*161+160,x-1
        txa
        sta dlist1+61
        lda random
        sta 256*162,x+39
        sta 256*162,x-1
        txa
        adc #80
        sta dlist1+64
        lda random
        sta 256*162+80,x+39
        sta 256*162+80,x-1
        txa
        adc #160
        sta dlist1+67
        lda random
        sta 256*162+160,x+39
        sta 256*162+160,x-1
        txa
        sta dlist1+70
        lda random
        sta 256*163,x+39
        sta 256*163,x-1
        txa
        adc #80
        sta dlist1+73
        lda random
        sta 256*163+80,x+39
        sta 256*163+80,x-1
        txa
        adc #160
        sta dlist1+76
        lda random
        sta 256*163+160,x+39
        sta 256*163+160,x-1

        mva #1 delay
        jsr wartes
        ldx var1
        clc
        inx
        cpx #40
        bne @+

        jmp loop

@       jmp @-

        .endp

    ;---------- Subroutinen ---------

        .proc dlist1

dlist   .by 117,117,117
        .by 66,210,155
        .by 66,0,156        
        .by 66,80,156
        .by 66,160,156

        .by 66,0,157
        .by 66,80,157
        .by 66,160,157

        .by 66,0,158
        .by 66,80,158
        .by 66,160,158  

        .by 66,0,159
        .by 66,80,159
        .by 66,160,159  

        .by 66,0,160        
        .by 66,80,160
        .by 66,160,160

        .by 66,0,161
        .by 66,80,161
        .by 66,160,161

        .by 66,0,162
        .by 66,80,162
        .by 66,160,162

        .by 66,0,163
        .by 66,80,163
        .by 66,160,163

        .by 65
        .wo dlist

        rts

        .endp

        .proc wartes
            clc
            ldx delay ; Warteschleife
st          
            lda RTCLOK+2

wa   
            cmp RTCLOK+2 
            beq wa 
            dex            
            bpl st 
            rts
     .endp   




        run main

AntwortZitat

Jetzt habe ich das mal erweitert und auf Antic D umgeschrieben... wir packen jetzt also 4kB an und machen damit über den gesamten Bildschirm von rechts nach links Grobscroll mittels Displaylistmanipulation.

Drei kurze .mov Beispiele mit unterschiedlichen Delays ... beim letzten habe ich die Warteschleife komplett rausgenommen und man sieht nur noch ein Pixelflimmern, da es einfach zu schnell ist. Im Grunde scrollt man jetzt fast ohne Zeitverzögerung was bei einer Auflösung von 4 kB für den Atari echt enorm ist. Man benötigt natürlich den doppelten Speicher - also 8 kB und ein wenig Code.

Mit dieser Technik werde ich jetzt auch das Parallaxing weiter bauen...

delay3.mov

delay2.mov

delay1.mov

Anhänge:
AntwortZitat

Ich verfolge dein "Entwicklungs-Tagebuch" hier sehr gespannt. (auch wenn ich nicht immer alles so nachvollziehen kann. Lustigerweise wollte ich die letzten Tage immer mal anfragen, ob du kleine Filmchen deiner Programmier-Fortschritte einstellen kannst um das besser nachvollziehen zu können.

Also bitte weiter posten und gerne immer mal wieder mit einem Filmchen aufhübschen. 😉

Ich bin wirklich beeindruckt, wie schnell Du vorankommst. Ich bin ja gerade selbst dabei, mich in die Assembler Programmierung einzuarbeiten. Vor einer Woche habe ich selbst mit dem Thema Scrolling begonnen, nachdem ich mich in die Display List und den DLI eingetüftelt hatte. ... und ich habe nach fünf Tagen gerade mal ein gegenläufiges horizontales Softscrolling hinbekommen:

https://1drv.ms/v/s!AubfF7Hbqd6zku8_0O9vQiSR6YFikQ

AntwortZitat

... ich habe den Code jetzt gerade ein wenig umgeschrieben und angepasst. Die Bildschirmspeicherung erfolgt jetzt indirekt indiziert und hierfür stelle ich 6 Variablen im Bereich Page 0 bereit. 6 Variablen deshalb, weil ich immer 3 Zeilen manipuliere - dabei brauche ich aber die doppele Anzahl weil ich die Zeichen in 2 Speicherbereiche ablege (um 40 versetzt). Alle drei Zeilen kommt dann eine Schleife und mit diesem Code kann ich 81 Zeilen ganz bequem scrollen. Warum nicht 100 Zeilen? Weil ich ja die Displaylist verbiege und das hier mit dem Befehl sta dlist1,x mache (weil es einfach ist) -> 27x9+7=250 .... da ist für x erstmal Schluss. Die letzten Zeilen muss man separat machen, oder die Variable für die Displaylist anders handhaben was natürlich geht... Wer Lust hat, kann den Code bzw. die Idee auch noch viel besser und intelligenter umsetzen...

Für den Parallax brauche ich nun folgendes: Das Feinscroll habe ich ja in drei Bereiche mit unterschiedlicher Geschwindigkeit getrennt, entsprechend muss auch der Grobscroll getrennt werden (den ich dann immer nach 8x Feinscroll aufrufe). Ich werde also drei Subroutinen erstellen: Grobscroll1..2..3 Zu dem Grobscroll kommt dann noch ein kleiner erster Landschaftsbereich dazu (statt Random), damit man auch was erkennen kann.

All das entwerfe ich so, daß ich das später in mein neues Spiel einbauen kann... ... das wird aber noch dauern, denn am Sa. fahre ich mal "kurz" nach Lyon rüber und schaue mir das Konzert von Rammstein an 😉

            org $1000


        icl '../hardware.txt'

zeilen = 230        
delay = 232
var1 = 233
var0 = 234
var80 = 236
var160 = 238        
var20 = 240
var280 = 242
var260 = 244    

        .proc main

        mwa #dlist1 560

loop    
        mva #0 zeilen
        lda #156 
        sta var0+1
        sta var80+1
        sta var160+1
        sta var20+1
        sta var280+1
        sta var260+1
        mva #0 var0
        mva #80 var80
        mva #160 var160
        mva #39 var20           ;0+39
        mva #119 var280         ;80+39
        mva #199 var260         ;160+39
        mva #0 zeilen

        ldy #1
        ldx #7

@       tya
        sta dlist1,x
        sta var1
        lda random
        sta (var20),y
        dey
        sta (var0),y
        iny
        inx
        inx
        inx
        tya
        adc #80
        sta dlist1,x
        lda random
        sta (var280),y
        dey
        sta (var80),y
        iny
        inx
        inx
        inx
        tya
        adc #160
        sta dlist1,x
        lda random
        sta (var260),y
        dey
        sta (var160),y
        iny
        inx
        inx
        inx
        stx var1

        inc var0+1
        inc var80+1
        inc var160+1
        inc var20+1
        inc var280+1
        inc var260+1

        clc
        inc zeilen
        #if .byte zeilen<#27        ; es werden 81 Zeilen grobgescrollt
        jmp @-
        #end

        mva #0 delay
        jsr wartes
        ldx var1
        clc
        iny
        cpy #41
        bne @+

        jmp loop

@       ldx#7
        mva #0 zeilen
        lda #156 
        sta var0+1
        sta var80+1
        sta var160+1
        sta var20+1
        sta var280+1
        sta var260+1

        jmp @-1

        .endp

    ;---------- Subroutinen ---------

        .proc dlist1

dlist   .by 117,117,117
        .by 77,210,155
        .by 77,0,156        
        .by 77,80,156
        .by 77,160,156

        .by 77,0,157
        .by 77,80,157
        .by 77,160,157

        .by 77,0,158
        .by 77,80,158
        .by 77,160,158  

        .by 77,0,159
        .by 77,80,159
        .by 77,160,159  

        .by 77,0,160        
        .by 77,80,160
        .by 77,160,160

        .by 77,0,161
        .by 77,80,161
        .by 77,160,161

        .by 77,0,162
        .by 77,80,162
        .by 77,160,162

        .by 77,0,163
        .by 77,80,163
        .by 77,160,163

        .by 77,0,164        
        .by 77,80,164
        .by 77,160,164

        .by 77,0,165
        .by 77,80,165
        .by 77,160,165

        .by 77,0,166
        .by 77,80,166
        .by 77,160,166  

        .by 77,0,167
        .by 77,80,167
        .by 77,160,167

        .by 77,0,168    
        .by 77,80,168
        .by 77,160,168

        .by 77,0,169
        .by 77,80,169
        .by 77,160,169

        .by 77,0,170
        .by 77,80,170
        .by 77,160,170

        .by 77,0,171
        .by 77,80,171
        .by 77,160,171

        .by 77,0,172
        .by 77,80,172
        .by 77,160,172

        .by 77,0,173
        .by 77,80,173
        .by 77,160,173

        .by 77,0,174
        .by 77,80,174
        .by 77,160,174

        .by 77,0,175
        .by 77,80,175
        .by 77,160,175

        .by 77,0,176    
        .by 77,80,176
        .by 77,160,176

        .by 77,0,177
        .by 77,80,177
        .by 77,160,177

        .by 77,0,178
        .by 77,80,178
        .by 77,160,178

        .by 77,0,179
        .by 77,80,179
        .by 77,160,179

        .by 77,0,180    
        .by 77,80,180
        .by 77,160,180

        .by 77,0,181
        .by 77,80,181
        .by 77,160,181

        .by 77,0,182
        .by 77,80,182
        .by 77,160,182

        .by 77,0,183
        .by 77,80,183
        .by 77,160,183

        .by 77,0,184
        .by 77,80,184
        .by 77,160,184

        .by 77,0,185
        .by 77,80,185
        .by 77,160,185

        .by 77,0,186
        .by 77,80,186
        .by 77,160,186

        .by 77,0,187
        .by 77,80,187
        .by 77,160,187



        .by 65
        .wo dlist

        rts

        .endp

        .proc wartes
            clc
            ldx delay ; Warteschleife
st          
            lda RTCLOK+2

wa   
            cmp RTCLOK+2 
            beq wa 
            dex            
            bpl st 
            rts
     .endp   




        run main

AntwortZitat

Hey Olix, vielen Dank! Das sieht schon echt super aus bei dir!!! So weit war ich vor einem Jahr noch lange nicht!! Vieles geht einfacher und schneller mit Eclipse/WUDSN/Mads... das kann ich immer wieder nur so sagen! Ich zeige es dir auf der Fujiama! gruß Peter

AntwortZitat

Prodehl schrieb: Vieles geht einfacher und schneller mit Eclipse/WUDSN/Mads... das kann ich immer wieder nur so sagen! Ich zeige es dir auf der Fujiama!

... super, da freue ich mich drauf.

Bis dahin bin ich mit meiner oldschool Entwicklungsumgebung aber noch ganz zufrieden. Noch macht mir das so Spaß und meine Übungsprogramme sind ja noch überschaubar.

Ich finde es zum lernen sogar produktiver, wenn man nicht zu viel Arbeit von der Entwicklungsumgebung abgenommen bekommt. Zumindest bei mir fördert das, das Verständnis der Vorgänge.

Aber wenn die Programme mal länger und die Aufgaben kniffeliger werden, so wie bei Dir, dann wollte ich auch nicht mehr im Windows-Editor schreiben und den Code dann per Copy-Paste in den Altirra übertragen. 😁

Und dann mal viel Spaß in Lyon mit Rammstein und einem Gläschen französischem Rotwein.

AntwortZitat

... die Arbeit frisst mich gerade auf, da wir Coronafälle bei uns haben und ich das auffangen muss... Heute habe ich endlich ein wenig Zeit gefunden, das Parallax weiterzuentwickeln. Ich möchte ja das Feinscroll mit dem Grobscroll nun verbinden und das Feinscroll habe ich ja schon mit DLI´s auseinandergerissen, so daß man z.B. drei (oder wahlweise mehr) Abschnitte das Bildschirmes mit unterschiedlichen Farben und Feinscroll-Geschwindigkeit darstellen kann. Das Grobscroll habe ich jetzt mit der Displaylistmanipulation erreicht - das war wegen des hoch auflösenden Antic D Modus notwendig - nun musste ich diesen Grobscroll auch in mehrere (auf den Feinscroll abgestimmten Bereich) separieren. Das war etwas knifflig und ein kleiner Bug ist auch noch drin, funktioniert aber jetzt. Ich kann also jetzt den Grobscroll in drei unterschiedlichen Subroutinen aufrufen, die Bereiche unabhängig voneinander hinsichtlich Geschwindigkeit und Breite usw. laufen lassen. Das binde ich jetzt in die andere Routine ein und dann sollte man das Parallax schön im Feinscroll darstellen können... das mache ich als nächstes!

Hier mal ein kleines Video vom Grobscroll dreier Bereiche in unterschiedlichen Geschwindigkeiten. Wie gesagt, 4kB Bildschirm mit DL-Manipulation. Um es besser zu sehen, habe ich einen hohen Verzögerungsfaktor eingebaut!!

Gruß Peter

Anhänge:
AntwortZitat

... puh... jetzt habe ich beide Programmteile kombiniert bekommen... also den Grobscroll mit DLI-Manipulation und den Feinscroll mit drei unterschiedlichen Geschwindigkeiten und Farben im DLI. Anbei ein kleines Video. Statt der Balken kann man jetzt quasi die Landschaft am Rand generieren. Das Timing war echt knifflig... in den drei DLI´s werden die Farben und die Feinscrolls getrennt und gesetzt - abgestimmt mit der Displaylist und den entsprechenden drei Einsprüngen, die nach Balkenhöhe an der richtigen Stelle stehen müssen. Das Grobscroll musste ich separieren, 2x wird der Grobscroll in der Hauptschleife ausgeführt, einmal direkt im DLI. Die unterschiedlichen Geschwindigkeiten werden im Hauptprogramm gezählt, der schnelle oberste Bereich bekommt zusätzlich noch einen Zähler im VBI.... Ich werde den Code noch etwas optimieren, wer ihn dann hier sehen möchte und optimieren möchte... einfach bekunden! LG Peter ... ich gehe jetzt mit grillen - mein Hirn ist schon gegrillt... parallax.MOV

Anhänge:
AntwortZitat

Müsste nicht der obere Bereich am langsamsten sein? Ansonsten Top!

Viel Spaß beim Grillen! Janko

Meine Projekte findest Du hier...

AntwortZitat

du meinst wegen der Perspektive… ja hast Recht! Das kann ich ja umändern! LG und danke!!

AntwortZitat

hier jetzt nochmal mit angepassten Geschwindigkeiten und einer Random-Landschaft! Irgendwo ist da noch ein Ruckeln drin... da muss ich noch Feintuning machen... Jetzt kann ich so langsam mal die Landschaft planen und dann gehts schon relativ direkt ins neue Spiel!

Gruß und einen schönen Sonntag

Peter parallax3.MOV

Anhänge:
AntwortZitat

und hier nochmal eine weitere Version... der rechte Bildschirmrand wird ständig per Random neu aufgebaut, schön flüssig läuft jetzt der Parallax, gleichzeitig habe ich statt der 4 Farben insgesamt 10 Farben benutzt. Das wird durch drei DLI´s erreicht (die auch für die Trennung des Feinscroll in drei Blöcken sorgen). Unten am Rand will ich noch etwas weiter runtergehen und mittels eines weiteren DLI wird dann später noch für die Anzeigen(Punkte, Fuel, etc.) auf einen normalen Charakterset umgeschaltet....

parallax4.MOV

Anhänge:
AntwortZitat

.... ich bin jetzt eigentlich erst einmal mit dem Thema Parallax fertig - besteht Interesse an dem Assembler-Code, oder macht das keinen Sinn, weil das nicht so wirklich oft genutzt wird? Wenn ja, dann würde ich den Code noch ein wenig aufarbeiten und mit Remarks versehen - jeder kann dann beliebig ausprobieren, ändern oder erweitern oder selbst nutzen. Es gibt da bestimmt auch ne Menge, was man noch viel effizienter programmieren kann!

Ansonsten werde ich mich jetzt sehr intensiv den Softwaresprites widmen...

Gruß Peter

AntwortZitat

Hi!

Selbst wenn Parallax-Scrolling nicht ganz so oft gebraucht wird, wäre es doch schade, wenn nun die Lösung (sprich Quelltext) hier nicht gepostet wird. Also ich würde es begrüßen, wenn Du den Quellcode hier posten würdest.

Grüße Janko

Meine Projekte findest Du hier...

AntwortZitat

Ja, auch ich würde das gerne studieren. Also gerne mit Kommentaren hier veröffentlichten.

AntwortZitat

hier das Listing:

                org $1000


;----- Definition der Hardwareregister -----

RANDOM = 53770
XITVBV = 58466
SETVBV = 58460
VDSLST = 512
NMIEN = 54286
wsync = 54282
hscrol = 54276
rtclok = 18

colpf0 = 53270
colpf1 = 53271
colpf2 = 53272
colpf3 = 53273

;-----  Definition dere Variablen ----

screen = 220
scrolm1 = 222
scrolm2 = 223
scrolm3 = 224
scrolindex1 = 225
scrolindex2 = 226
scrolindex3 = 227
display = 228


zeilen = 230        
delay = 232
var1 = 233
var0 = 234
var80 = 236
var160 = 238        
var20 = 240
var280 = 242
var260 = 244



grob1y = 1000   
grob2y = 1001
grob3y = 1002
grobn = 1003

groba = 1004            



            .proc main

            mwa #39936 display      ;--- hier fängt die Bildschirmadresse an 0,156 = 256x156
            mwa #dlist 560          ;--- die neue Displaylist wird auf 560 umgebogen ANTIC D
            ldy #0                  ;der VBI wird initialisiert
            ldx #0
            ldx #>vbinter           ;VB-Interrupt VektorHi
            ldy #<vbinter           ;VB-Interrupt VektorLo
            lda #7                  ;Deferred Mode mit lda #7 festlegen
            jsr setvbv              

            lda #<dli0              ;der 1. Displaylist-Interrupt wird initialisiert    
            sta VDSLST
            lda #>dli0
            sta VDSLST+1
            lda #192
            sta NMIEN

            ldy #0
            lda #4
            sta scrolm1
            sta scrolm2
            sta scrolm3



loop                                ;hier steht das Hauptprogramm



            jsr scrolling           ;der Scrollaufruf

            mva #0 delay            ;eine Warteschleife 1/50sek.
            jsr wartes


            jmp loop

            .endp



            ; ---------------------------- S U B R O U T I N E N ----------------------------------

            .proc scrolling             
            #if .byte scrolm2<=#4       ; Zähler für Feinscroll - in Antic D von 8 -> 4
            jsr grob2                   ; der Grobscroll für den mittleren Bereich wird ausgeführt
            mva #8 scrolm2
            #end

            #if .byte scrolm3<=#4
            mva #8 scrolm3              ; Grobscroll unterer Bereich
            jsr grob3
            #end
                                        ; hier wird die Geschwindigkeit gesteuert
            inc scrolindex1
            inc scrolindex2
            inc scrolindex3

            #if .byte scrolindex1=#3
            mva #0 scrolindex1
            dec scrolm1
            #end
            #if .byte scrolindex2=#2
            mva #0 scrolindex2
            dec scrolm2
            #end
            #if .byte scrolindex3=#1
            mva #0 scrolindex3
            dec scrolm3
            #end
            rts
            .endp
            .proc grobmain              ;diese Routine macht den Grobscroll für Grob1,2,3

@           tya
            sta dlist,x                 ;hier wird die jeweilige DList pro Zeile geschoben
            lda random                  
            sta (var20),y               ;Wert rechts außen speichern (sichtbar) 
            dey
            sta (var0),y                ;Wert um eins verschoben in den unsichtbaren Bereich schieben
            iny
            inx                         ;3x inx für die nächste DL-Zeile
            inx
            inx
            tya
            adc #80                     ;wir bearbeiten in dieser Routine immer 3 DL Zeilen
            sta dlist,x                 ;0 / 80 / 160 - da sind immer 2x40 Zeilen drin - die sichtbare und die unsichtbare
            lda random                  ;und nach 3 Zeilen wird einfach das High Byte incrementiert 
            sta (var280),y              ;danach startet diese Routine erneut für einen 3er Block
            dey
            sta (var80),y
            iny
            inx
            inx
            inx
            tya
            adc #160                    ;3.Zeile
            sta dlist,x
            lda random
            sta (var260),y
            dey
            sta (var160),y
            iny
            inx
            inx
            inx
            inc var0+1                  ;das High Byte wird für alle incrementiert
            inc var80+1
            inc var160+1
            inc var20+1
            inc var280+1
            inc var260+1

            clc
            inc zeilen                  ;Anzahl der Zeilen pro Block
            #if .byte zeilen<grobn      ;es werden max.81 Zeilen grobgescrollt (dann geht x über 255)
            jmp @-
            #end
            rts
            .endp
            .proc grob1

            mva #0 zeilen
            lda #156
            sta var0+1
            sta var80+1
            sta var160+1
            sta var20+1
            sta var280+1
            sta var260+1
            mva #0 var0
            mva #80 var80
            mva #160 var160
            mva #43 var20           ;0+39
            mva #123 var280         ;80+39
            mva #203 var260         ;160+39
            mva #0 zeilen
            ;mva #0 groba
            ;#if .byte grob1y<#1
            mva random groba        ;in groba kommt rein was rechts geprintet  wird
            ;#end
            ldx #7                  ;bei 7 wird die erste Displaylist manipuliert - dann immer plus 3
            mva #2 grobn            ;der erste Block ist 2x3 Zeilen breit
            ldy grob1y
            #if .byte grob1y=#48    ;wegen des DLI haben wir nicht 40 Zeichen pro Zeile sondern 48
            #end
            jsr grobmain
            inc grob1y

            #if .byte grob1y=#47
            mva #0 grob1y

            #end

            rts
            .endp
            .proc grob2

            mva #0 zeilen

            lda #158
            sta var0+1
            sta var80+1
            sta var160+1
            sta var20+1
            sta var280+1
            sta var260+1
            mva #0 var0
            mva #80 var80
            mva #160 var160
            mva #43 var20           ;0+39
            mva #123 var280         ;80+39
            mva #203 var260         ;160+39
            mva #0 zeilen
            ;mva #0 groba
            ;#if .byte grob2y<#1
            mva random groba
            ;#end
            ldx #25
            mva #4 grobn
            ldy grob2y
            #if .byte grob2y=#48
            #end
            jsr grobmain
            inc grob2y

            #if .byte grob2y=#47
            mva #0 grob2y

            #end

            rts
            .endp
            .proc grob3
            lda #162
            sta var0+1
            sta var80+1
            sta var160+1
            sta var20+1
            sta var280+1
            sta var260+1
            mva #0 var0
            mva #80 var80
            mva #160 var160
            mva #43 var20           ;0+39
            mva #123 var280         ;80+39
            mva #203 var260         ;160+39
            mva #0 zeilen
            ;mva #0 groba
            ;#if .byte grob3y<#1
            mva random groba
            ;#end
            ldx #61
            mva #21 grobn
            ldy grob3y
            #if .byte grob3y=#48
            #end
            jsr grobmain
            inc grob3y

            #if .byte grob3y=#47
            mva #0 grob3y

            #end

            rts
            .endp   
            .proc wartes
            clc
            ldx delay ; Warteschleife
st          
            lda RTCLOK+2

wa   
            cmp RTCLOK+2 
            beq wa 

            dex            
            bpl st 
            rts
            .endp   
            .proc dli0              ;Farbe mittlerer Streifen
            phr
            sta wsync

            mva #2 colpf0
            mva #6 colpf1   
            mva #10 colpf2
            mva #14 colpf3
            mva scrolm2 hscrol      ;hier wird der Feinscroll gesteuert
            #if .byte scrolm1<=#4   ;der erste Balken wird im 1.DLI gesteuert
            jsr grob1               ;der mittlere und untere im Hauptprogramm
            mva #8 scrolm1
            #end
            mwa #dli1 512           ;hier wird im 1.DLI der 2.DLI initialisiert     
            plr
            rti
            .endp
            .proc dli1              ;Farbe unterer Streifen
            phr

            mva scrolm3 hscrol      ;hier wird der Feinscroll gesteuert
            mva #37 colpf1
            mva #101 colpf0
            mva #168 colpf2
            mva #246 colpf3
            mwa #dli2 512           ;der 2. DLI initialisiert den 3.DLI

            plr
            rti
            .endp       
            .proc dli2
            phr

            mva scrolm1 hscrol      ;hier wird der Feinscroll gesteuert

            mwa #dli0 512           ;der 3.DLI initialisiert den 1.DLI

            plr
            rti
            .endp
            .proc vbinter           ;den VBI brauchen wir aktuell nur für die Farbe des ersten Blocks



            pha
            txa
            pha
            tya
            pha


            mva #222 colpf1
            mva #68 colpf0
            mva #182 colpf2
            mva #38 colpf3


            pla
            tay
            pla
            tax
            pla
            jmp xitvbv          ;vb-interrupt wird über xitvbv beendet!!

            .endp

dlist       .by 117,117,117         ;dies ist die Displaylist
        .by 93,210,155          ;keine Ahnung warum, aber diese scheinbar unnötige Zeile brauche ich hier...
        .by 93,0,156            ;hier geht die erste Zeile des ersten Blocks los
        .by 93,80,156           ;93= 64 (Sprungbefehl)+16 (HSCROL aktiv) +13 (Antic D)
        .by 93,160,156

        .by 93,0,157
        .by 93,80,157
        .by 221,160,157         ;93 +128 (Interrupt wird ausgelöst)     

        .by 93,0,158
        .by 93,80,158
        .by 93,160,158  

        .by 93,0,159
        .by 93,80,159
        .by 93,160,159  

        .by 93,0,160        
        .by 93,80,160
        .by 93,160,160

        .by 93,0,161
        .by 93,80,161
        .by 221,160,161

        .by 93,0,162
        .by 93,80,162
        .by 93,160,162

        .by 93,0,163
        .by 93,80,163
        .by 93,160,163

        .by 93,0,164        
        .by 93,80,164
        .by 93,160,164

        .by 93,0,165
        .by 93,80,165
        .by 93,160,165

        .by 93,0,166
        .by 93,80,166
        .by 93,160,166  

        .by 93,0,167
        .by 93,80,167
        .by 93,160,167

        .by 93,0,168    
        .by 93,80,168
        .by 93,160,168

        .by 93,0,169
        .by 93,80,169
        .by 93,160,169

        .by 93,0,170
        .by 93,80,170
        .by 93,160,170

        .by 93,0,171
        .by 93,80,171
        .by 93,160,171

        .by 93,0,172
        .by 93,80,172
        .by 93,160,172

        .by 93,0,173
        .by 93,80,173
        .by 93,160,173

        .by 93,0,174
        .by 93,80,174
        .by 93,160,174

        .by 93,0,175
        .by 93,80,175
        .by 93,160,175

        .by 93,0,176    
        .by 93,80,176
        .by 93,160,176

        .by 93,0,177
        .by 93,80,177
        .by 93,160,177

        .by 93,0,178
        .by 93,80,178
        .by 93,160,178

        .by 93,0,179
        .by 93,80,179
        .by 93,160,179

        .by 93,0,180    
        .by 93,80,180
        .by 93,160,180

        .by 93,0,181
        .by 93,80,181
        .by 93,160,181

        .by 93,0,182
        .by 93,80,182
        .by 93,160,182

        .by 93,0,183
        .by 93,80,183
        .by 93,160,183

        .by 93,0,184
        .by 93,80,184
        .by 93,160,184

        .by 93,0,185
        .by 93,80,185
        .by 93,160,185

        .by 93,0,186
        .by 93,80,186
        .by 93,160,186

        .by 93,0,187
        .by 93,80,187
        .by 221,160,187

        .by 65
        .wo dlist
            run main
AntwortZitat

Die PF Assembler Ecke aus der CK 10-11/86 beschäftigt sich übrigens mit DLIs. Gruß Wolfgang

AntwortZitat